/* 
Copyright (c) 2004,2005, 2006, 2007, 2008 University of Illinois 

All rights reserved.

Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
are met:

1. Redistributions of source code must retain the above copyright
   notice, this list of conditions and the following disclaimer.

2. Redistributions in binary form must reproduce the above copyright
   notice, this list of conditions and the following disclaimer in the
   documentation and/or other materials provided with the distribution.

3. The name of the author may not be used to endorse or promote products
   derived from this software without specific prior written permission.

THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/

/* Functions for the RDF Role browser
 * romanows, 6/1/06
 */
AccessibilityExtension.ns(function() { with (AccessibilityExtension.LIB) {

	var AE = AccessibilityExtension.ns;  
	AE.dialogName = "accessext-form-list-dhtmlrdfroles";	

	var tbObj;
	var subClassOfGraph;
	var rootNode;
	var dialogInitFinished = false;
	var rABP;
	
	function RDFRoleObjectDisplayDetails() {}
	RDFRoleObjectDisplayDetails.prototype = {
		dataElementNames : ['maintype','role','isonpage','subject'], //,'namespace'
		columnHeaders : ['column.header.maintype.label','column.header.role.label','column.header.isonpage.label','widget.description.hbox.label'], //,'column.header.namespace.label'
		
		accessIssuesDataElementNames : [],
		accessIssuesMessages : [],
	}
	var RDFRoleObjectDisplayDetails = new RDFRoleObjectDisplayDetails();
	
	// Constructor
	function RDFRoleObject(torder, maintype, role, isonpage, namespace, subject) {
		this.order = torder;
		this.maintype = maintype;
		this.role = role;
		this.namespace = namespace;
		this.isonpage = isonpage;
		this.subject = subject;
	}
	RDFRoleObject.prototype = {
		node : null,
		maintype : null, // this is widget, structural, or other
		role : null,
		isonpage : null,
		namespace : null,
		subject : null,
		display : true,	
		displayDetails: RDFRoleObjectDisplayDetails,
		getTreeNode : function(windoc) {
			return accesxt_generateTreeboxResults(windoc,this,['maintype','role','isonpage','namespace','subject']);
		},
	   getNoteText : function() {
			return '';
		}
	}

AccessibilityExtension.LIB.extend(AccessibilityExtension.LIB,
{
	initTreeboxDHTMLRoles: function() {
		var roleColumnHeaders =loadRoleColumnHeaders();			
		tbObj = newTreeboxObject('treebox',roleColumnHeaders,'list-header-role');
	},
	
	// Copied from RefreshList, should refresh the view without reloading dataarray from the DOM tree
	RefreshListView: function() {
		var tempCurrentIndex=AE.treebox.currentIndex;
	
		tbObj.setDataArray(AE.dataarray);
		UpdateTreeView();
		AE.treebox.view.selection.select(tempCurrentIndex);
	},
	
	// Scans the DOM to create a list of relevant objects and updates our tree view
	RefreshList: function() {
		updatePointers();
		
		ParseDocument(AE.thewindow.document);
		tbObj.setDataArray(AE.dataarray);
		UpdateTreeView();
	},
	
	/**
	 * for loading the Role list headers.
	 * @return array of column headers for the role list
	 * @author Sandy Foltz
	*/
	loadRoleColumnHeaders: function() {
		var cols = new Object();
		cols['list-header-maintype'] = 'maintype';
		cols['list-header-role'] = 'role';
		cols['list-header-isonpage'] = 'isonpage';	
		cols['list-header-namespace'] = 'namespace';	
		cols['list-header-subject'] = 'subject';	
		return cols;	
	},
	
	InitAccessibilityExt: function() {
		InitAccessibilityExt_common();
	},
	
	// Uses XPATH to find elements with x2 widget roles, returns an XPath result
	ParseDocument: function(node) {
	    
	   AE.sortColumn = "list-header-role";
	   loadWairolesProperties();
	   
	   callback = {
	      run: function() {
	         var wairoles = [];
	         results = myRDF.Match(null, null, 'http://www.w3.org/1999/02/22-rdf-syntax-ns#type', 'http://www.w3.org/2002/07/owl#Class');
	         re = /^.*#(.*)$/;
	         for(var i = 0; i < results.length; i++) {
	            wairoles.push(results[i].subject.match(re)[1]);
	         }
	         return wairoles;
	      }
	   }
	   
	   var myRDF = new RDF();
	   //var wairoles = myRDF.getRDFURL('http://www.w3.org/2005/01/wai-rdf/GUIRoleTaxonomy#', callback);
	   var wairoles = myRDF.getRDFURL("http://codetalks.org/source/tools/Test%20Pages/aria.rdf", callback);
	  
	   var xp = ''; //"//*[" + XPathPseudoNamespaceSearchPredicate('@x:role|@x2:role|@role',wairoles[0]) + "]"; 
	   for(var i=1; i<wairoles.length; i++) {
	   		var roleLocation = getRoleLocation(wairoles[i]);
			if (roleLocation != -1) {
				var subclassof = AE.wairoleProperties[roleLocation].subClassOf[0];
				var numParents = AE.wairoleProperties[roleLocation].subClassOf.length;
				
				if (numParents > 1) { subclassof += ' +';}
		   		xp = "//*[" + XPathPseudoNamespaceSearchPredicate('@x:role|@x2:role|@role',wairoles[i]) + "]"; 
		
				var xpathResult = node.evaluate(xp, node, accessext_NSResolver, XPathResult.ANY_TYPE,null);
				var r = xpathResult.iterateNext();
			
				if (r == null) {
	   				AE.dataarray[AE.dataarray.length] = new RDFRoleObject(AE.dataarray.length, subclassof, wairoles[i], false, 'wairole', '');
				} else {
					AE.dataarray[AE.dataarray.length] = new RDFRoleObject(AE.dataarray.length,subclassof, wairoles[i], true, 'wairole', '');
					r = xpathResult.iterateNext();
				}
			}
	   }
	},
	
	// When a row in the treebox_main is selected, this is called
	accessext_handle_treebox: function() {
		// If we've selected something sensical
		if(AE.treebox.currentIndex < 0 || AE.treebox.currentIndex >= AE.dataarray.length)
			return;
	
		var subject = AE.dataarray[AE.treebox.currentIndex].role;
		updateState(subject);
		updateLineage(subject);
		updateOther(subject);
		 
		var noteElement = document.getElementById("widget-description-textbox");
		if (null!= noteElement) {
			var roleLocation = getRoleLocation(subject);
			try {
	        	noteElement.setAttribute("value", AE.wairoleProperties[roleLocation].description);
			}
			catch (e) {
				alert(e)
	       		noteElement.setAttribute("value",'');
			}
		}	
	
	},
	
	updatePointers_common: function() {
		//thewindow & mydoc are retreived differently for dialog vs sidebar
		try { // dialog way first
			AE.thewindow = window.opener.parent._content;
		} catch(e) { //SMF 8/13/07 tried this, window.self, window.opener.parent.content, window, window.frameElement.ownerDocument
			AE.thewindow = window.parent._content;
		}
		/*
		 * SF 8/10/07 highlighting and catching button pushes are not being captured when in sidebar
		 * error may be here or in each individual area.
		 */
		AE.mydoc = AE.thewindow.document;		
		AE.treebox = document.getElementById("treebox");
		AE.dataarray = new Array();
	},
	
	updatePointers: function() {
	   updatePointers_common();   
	   initTreeboxDHTMLRoles();
	},
	
	UpdateTreeView: function() {
		var cols = loadRoleColumnHeaders();	
		UpdateTreeView_common(AE.treebox,'role',AE.sortColumn,cols,AE.dataarray);
	},
	
	roleAncestorsByPos: function(roleLocation) {
		var retStr = '';
		for(var i=0; i< AE.wairoleProperties[roleLocation].subClassOf.length; i++) {
			var nextLoc = getRoleLocation(AE.wairoleProperties[roleLocation].subClassOf[i]);
			if (nextLoc != -1){
				retStr += nextLoc + ' ';
				retStr += roleAncestorsByPos(nextLoc);
			}
		}
	
		rABP = retStr;
		return retStr; 
	},
	
	updateState: function(selectedSubject) {
		var accestorsPos;
		var targetArray = new Array();
		//clear the old treebox if any existing nodes
		var treechildren = document.getElementById("tabpanel-treebox-states-treechildren");
		while(treechildren.hasChildNodes()){
			treechildren.removeChild(treechildren.firstChild);
		}
		
		var roleLocation = getRoleLocation(selectedSubject);
		if(AE.wairoleProperties[roleLocation].subClassOf.length > 0) {
			rABP = '';
			roleAncestorsByPos(roleLocation); //sets rABP
			if (rABP.length >= 2) {rABP = rABP.substring(0, rABP.length-1);}
			accestorsPos = roleLocation + ' ' + rABP;
			targetArray = accestorsPos.split(" ");
			
		    // Remove duplicates from list
		    targetArray.sort();
		    for(var j=0; j<targetArray.length; j++) {
		       if( targetArray[j] == targetArray[j+1] ) {
		          targetArray.splice(j+1,1); // remove the next item (duplicate)
		          j--; // check this item again now that we've modified the array
		       }
		    }
		} else {
			targetArray.push(roleLocation);
		}
		var statesInSelected = new Array();
		var statesFromAncestor = new Array();
		for(var i=0; i< targetArray.length; i++) {
			var currLoc = targetArray[i];
			for(var j=0; j<AE.wairoleProperties[currLoc].supportedStates.length; j++) {
				statesInSelected.push(AE.wairoleProperties[currLoc].supportedStates[j]);
				statesFromAncestor.push(AE.wairoleProperties[currLoc].id);
			}
		}
		
		// Output to the tabpanel
		var treerow, treeitem;
		for(var k=0; k<statesInSelected.length; k++) {
			treeitem = createXULElement("treeitem");
			treerow = createXULElement("treerow");
			treerow.appendChild(createTreecell(rdfGetName(statesInSelected[k])));
			treerow.appendChild(createTreecell(rdfGetName(statesFromAncestor[k])));			
			treerow.appendChild(createTreecell('wairole')); //rdfGetNamespace(statesInSelected[k])));					
			treeitem.appendChild(treerow);
			treechildren.appendChild(treeitem);
		}
	},
	
	// Sets the selection in the Lineage treebox to be the same as the given subject
	updateLineage: function(selectedSubject) {
		//clear the old treebox if any existing nodes
		var treechildren = document.getElementById("tabpanel-tree-lineage-treechildren");
		while(treechildren.hasChildNodes()){
			treechildren.removeChild(treechildren.firstChild);
		}
	
		var treebase = document.getElementById("tabpanel-tree-lineage-treechildren");
		var constructXULTreeFromGraphBackRelation = function(roleLocation,treebase) {
			try {
				var treeitem = createTreeitem();
				var treerow = createXULElement("treerow");
				treerow.appendChild(createTreecell(AE.wairoleProperties[roleLocation].id));
				treeitem.appendChild(treerow);
			
				// iterate over backRelation nodes and recursivly build tree
				if(AE.wairoleProperties[roleLocation].subClassOf.length > 0) {
					var treechildren = createXULElement("treechildren");
					for(var i=0; i<AE.wairoleProperties[roleLocation].subClassOf.length; i++) {
						var nextLoc = getRoleLocation(AE.wairoleProperties[roleLocation].subClassOf[i]);
						if (nextLoc != -1) {
							constructXULTreeFromGraphBackRelation(nextLoc,treechildren);
						}
					}
					treeitem.appendChild(treechildren);
				}
				treebase.appendChild(treeitem);				
			} catch (ex) {
				accessext_consoleDump('exception: ', ex);
			}
		}
		var roleLocation = getRoleLocation(selectedSubject);
		constructXULTreeFromGraphBackRelation(roleLocation,treebase);	
	
	},
	
	updateOther: function(selectedSubject) {
		var accestorsPos;
		var targetArray = new Array();
		//clear the old treebox if any existing nodes
		var treechildren = document.getElementById("tabpanel-treebox-other-treechildren");
		while(treechildren.hasChildNodes()){
			treechildren.removeChild(treechildren.firstChild);
		}
		
		var roleLocation = getRoleLocation(selectedSubject);
		// Output to the tabpanel
		var treerow, treeitem;
		for(var k=0; k<AE.wairoleProperties[roleLocation].mustContain.length; k++) {
			treeitem = createXULElement("treeitem");
			treerow = createXULElement("treerow");
			treerow.appendChild(createTreecell('mustContain'));
			treerow.appendChild(createTreecell(AE.wairoleProperties[roleLocation].mustContain[k]));			
			treeitem.appendChild(treerow);
			treechildren.appendChild(treeitem);
		}
		for(var k=0; k<AE.wairoleProperties[roleLocation].relatedConcept.length; k++) {
			treeitem = createXULElement("treeitem");
			treerow = createXULElement("treerow");
			treerow.appendChild(createTreecell('relatedConcept'));
			treerow.appendChild(createTreecell(AE.wairoleProperties[roleLocation].relatedConcept[k]));			
			treeitem.appendChild(treerow);
			treechildren.appendChild(treeitem);
		}
	},
	
	ARIARoleRefresh: function() {
		tempCurrentIndex=document.getElementById('treebox').currentIndex;
	  	RefreshList();
		if (tempCurrentIndex > document.getElementById('treebox').length) {
			tempCurrentIndex = 0;
		}
		document.getElementById('treebox').view.selection.select(tempCurrentIndex);
		document.getElementById('treebox').focus();
	}
});
	if (AccessibilityExtension.LIB.InitAccessibilityExt) AccessibilityExtension.LIB.InitAccessibilityExt();	
}});